/**
 * ViewInterface.java
 * ************************** 
 * @date Mar 17, 2011
 * @author Michele Tamburini
 * 
 * **************************
 */
package gossipServices.basic.view;

import gossipServices.basic.nodeDescriptors.NodeDescriptor;
import gossipServices.basic.nodeDescriptors.comparators.NodeDescriptorComparator;

import java.io.Serializable;

/**
 * Description: 
 * 
 * This is the interface that is expected from a view,
 * according to:
 * "Gossip-based Peer Sampling", M. Jelasity, S. Voulgaris, 
 * R. Guerraoui, A. Kermarrec, M. Van Steen.
 * 
 * Each Node keep a PartialView.
 * In short a PartialView is the "local view" that a Node has
 * of its neighborhood. The PartialView contains a collections 
 * of NodeDescriptor(s), in which each of them 
 * links the current Node to the one described by the selected NodeDescritor. 
 */
public interface PartialView extends Serializable {
	
	/**
	 * 
	 * @author michele
	 * 
	 * 
	 * Description: 
	 * Enumerations that lists the possible method of Peer Selection.
	 * By 'rand' a random peer will be extracted during the select peer.
	 * By 'tail' the tail node is otherwise extracted.
	 */
	public static enum PEER_SELECTION_ENUM {rand, tail};
	
	/**
	 * Returns a NodeDescriptor, that links to another Node, from
	 * the local PartialView.
	 * @param selection
	 * @return
	 */
	public NodeDescriptor selectPeer(PEER_SELECTION_ENUM selection);
	
	/**
	 * The Select function is supposed to perform some actions on the view.
	 * (Please be sure to be in thread-safe conditions before calling it!)
	 * In order the list of operations is:
	 *   append(bufferp);
	 *   removeDuplicates();
	 *   removeOldItems(min(H, view.size()-c));
	 *   removeHead(min(S, view.size()-c));
	 *   removeAtRandom(view.size-c);  
	 * 
	 * The 'c' parameter is supposed to be the PartialView length. 
	 * Because of append a removal operation the actual size may be larger
	 * than 'c'. However a the returning of select the PartialView
	 * size must be ensured to be equal to 'c'.
	 * Parameters 'H' and 'S' indicate the Healer and Swapper 
	 * elements in the PartialView. 
	 * 'bufferp' is the incoming ration of the view from another Node.
	 * Return true if no problem is encountered, false
	 * otherwise.
	 * 
	 *  Please refere to the paper for a complete understanding of 
	 *  how this method works.
	 * 
	 * @param c
	 * @param H
	 * @param S
	 * @param bufferp
	 * @return
	 */
	public boolean select(int c, int H, int S, 
			PartialView bufferp, NodeDescriptor myDescriptor);
	
	/**
	 * Permute: moves the H oldest elements at the end of the view,
	 * leaving the others at their own positions.
	 * Return true if no problem is encountered, false
	 * otherwise.
	 * @param H
	 * @return
	 */
	public boolean permute(int H);
	
	/**
	 * Increase the age of all NodeDescriptor(s) by 1.
	 * Return true if no problem is encountered, false
	 * otherwise.
	 * @return
	 */
	public boolean increaseAge();
	
	/**
	 * Append the input PartialView to the current one. 
	 * No other actions are performed but the appending.
	 * Return true if no problem is encountered, false
	 * otherwise.
	 * @param v
	 * @return done : boolean
	 */
	public boolean append(PartialView v);
	
	/**
	 * Returns a new PartialView containing a 
	 * number of 'elements' elements starting 
	 * from the head of the actual PartialView. 
	 * @param elements
	 * @return viewPortion : PartialView
	 */
	public PartialView head(int elements);
	
	/**
	 * Returns the size of the current PartialView.
	 * @return size : int
	 */
	public int size();
	
	/**
	 * It merges the current view with the PartialView buffer
	 * in input as parameter. 
	 * It removes the duplicates ensuring that only one entry of  
	 * each NodeDescriptor is contained into the view.
	 * So the new PartialView keeps only one NodeDescriptor for each node.
	 * The merge() function also has to preserve the whole old view
	 * by adding only the new incoming NodeDescriptor(s).
	 * Returns true if none errors occurs, false otherwise.
	 * @param buffer : PartialView
	 * @return done : boolean
	 */
	public boolean merge(PartialView buffer);
	
	/*
	 * *********************************************************
	 * *************** USEFUL PARTIAL VIEW API *****************
	 * *********************************************************
	 * What follows is a not-official (not explicitly built in the 
	 * paper) set of API of a PartialView. These functions may
	 * result useful for debugging or other sort of 
	 * implementation features.
	 * *********************************************************
	 */
	
	/**
	 * Add the input NodeDescritor 'node' to the PartialView.
	 */
	public boolean insertNodeDescriptor(NodeDescriptor node);
	
	/**
	 * Remove from the PartialView all duplicates NodeDescriptors.
	 * Return true if no problem is encountered, false
	 * otherwise. 
	 * @return done : boolean
	 */
	public boolean removeDuplicates();
	
	/**
	 * Removes the 'elements' oldes items from the PartialView.
	 * 'c' is supposed to be the fixed size of the view.
	 * Return true if no problem is encountered, false
	 * otherwise.
	 * @param elements
	 * @param c
	 * @return done : boolean
	 */
	public boolean removeOldItems(int elements, int c);
	
	/**
	 * Removes a number of 'elements' elements from the head of 
	 * the PartialView. 
	 * Return true if no problem is encountered, false
	 * otherwise.
	 * @param elements
	 * @return
	 */
	public boolean removeHead(int elements);
	
	/**
	 * Removes at random a number of 'elements' NodeDescriptors 
	 * from the View.
	 * Return true if no problem is encountered, false
	 * otherwise.
	 * @param elements
	 * @return
	 */
	public boolean removeAtRandom(int elements);
	
	/**
	 * NOTE: the use of this method is discouraged.
	 * Return the i-th NodeDescriptor kep by the PartialView.
	 * NOTE:
	 * Recall that because of the continuing changing of the 
	 * view during the cycles,
	 * any assumption on the position of a NodeDescriptor
	 * may probably 
	 * leads to a wrong assessment. 
	 * @param index
	 * @return
	 */
	public NodeDescriptor getAt(int index);
	
	public NodeDescriptor find(String nodeName);
	
	public boolean remove(NodeDescriptor node);
	
	
	public void applyComparator(NodeDescriptorComparator comparator);
}
